#ifndef TERRAMODEL_H
#define TERRAMODEL_H

/**
 * \brief TerraModel类提供地形数据的存储与索引服务
 */

#include <memory>
#include "../external/skip-grid/skipgrid.h"
#include <QString>
#include <QColor>
#include <QMap>
#include <mutex>

class TerraModel
{
public:
    using SkipGrid = SkipGrid<int, unsigned, 16>;

    // 材料信息
    struct Material
    {
        // 注释
        QString comment;
        // 名称
        QString name;
        // 声阻抗系数
        int coef;
        // 颜色
        QColor color;
    };

    // 瓦片单元（材料信息 + 坐标信息）
    struct Tile
    {
        // 坐标
        double x, y;

        // 材料
        unsigned id;
    };

    TerraModel();

    // 坐标值 -> 索引值
    void coordinateToIndex(double x, double y, int& ix, int& iy)
    {
        ix = int( floor(x / _resolution) );
        iy = int( floor(y / _resolution) );
    }

    // 索引值 -> 坐标值
    void indexToCoordinate(int ix, int iy, double& x, double& y)
    {
        x = (ix + 0.5) * _resolution;
        y = (iy + 0.5) * _resolution;
    }

    // 获取瓦片列表
    void toVector(std::vector<struct Tile> &vec);

    // 获取瓦片列表，且  x_min <= vec[i].x <= x_max && y_min <= vec[i].y <= y_max
    void toVector(std::vector<struct Tile> &vec, double x_min, double x_max, double y_min, double y_max);

    // 设置材料ID
    void setMaterial(unsigned id)
    {
        _material = id;
    }

    // 载入地形数据
    void loadTerra(const QString& path);

    // 保存地形数据
    void saveTerra(const QString& path);

private:
    // 地形数据
    std::shared_ptr<SkipGrid> _grids = nullptr;
    // 地形数据保护锁（否则在大规模读写时容易崩溃，亲测）
    std::mutex _grids_mtx;

    // 分辨率
    double _resolution = 0.1;

    // 索引范围
    int _min_index = -100000;
    int _max_index = 100000;

    // 地形材料表
    QMap<unsigned, struct Material> _material_table;

    // 读取配置
    void readConfig();

    // 当前选中材料id
    unsigned _material = 0;

    // 方便地形图层直接访问数据
    friend class TerraView;
    friend class TerraBrush;
};

extern std::shared_ptr<TerraModel> terra_model;

#endif // TERRAMODEL_H
